#include "../coredef.h"
#include "cc.h"

#define STRING_NONE				0
#define STRING_CHARSTRING		1
#define STRING_WIDESTRING		2

static U4 ulPreTokenKind = 0;
static AST gblCurrToken;

typedef struct _RESERVEDREGIST {
	PSZ pszToken; /* ﾄｰｸﾝの文字列			*/
	U4 ulKind; /* ﾄｰｸﾝ種別				*/
	S4 iNext; /* 次のｲﾝﾃﾞｯｸｽ			*/
} RESERVEDREGIST, *PRESERVEDREGIST;

static S4 tiIdxReservedWord[256];

static RESERVEDREGIST stReservedWord[] = {
		{ "if", xLEX_IF, -1 },
		{ "int",xLEX_INT, -1 },
		{ "auto", xLEX_AUTO, -1 },
		{ "break", xLEX_BREAK, -1 },
		{ "case", xLEX_CASE, -1 },
		{ "char", xLEX_CHAR, -1 },
		{ "const",xLEX_CONST, -1 },
		{ "continue", xLEX_CONTINUE, -1 },
		{ "default", xLEX_DEFAULT, -1 },
		{ "double", xLEX_DOUBLE, -1 },
		{ "do", xLEX_DO, -1 },
		{ "else", xLEX_ELSE, -1 },
		{ "enum",xLEX_ENUM, -1 },
		{ "extern", xLEX_EXTERN, -1 },
		{ "float",xLEX_FLOAT, -1 },
		{ "for", xLEX_FOR, -1 },
		{ "goto", xLEX_GOTO, -1 },
		{ "long", xLEX_LONG, -1 },
		{ "register", xLEX_REGISTER, -1 },
		{ "restrict", xLEX_RESTRICT, -1 },
		{ "return", xLEX_RETURN, -1 },
		{ "short", xLEX_SHORT, -1 },
		{ "signed", xLEX_SIGNED, -1 },
		{ "sizeof", xLEX_SIZEOF, -1 },
		{ "static", xLEX_STATIC, -1 },
		{ "struct", xLEX_STRUCT, -1 },
		{ "switch", xLEX_SWITCH, -1 },
		{ "typedef", xLEX_TYPEDEF, -1 },
		{ "union", xLEX_UNION, -1 },
		{ "unsigned", xLEX_UNSIGNED, -1 },
		{ "void", xLEX_VOID, -1 },
		{ "volatile", xLEX_VOLATILE, -1 },
		{ "while", xLEX_WHILE, -1 },
		{ "__interrupt", xLEX_INTERRUPT, -1 },
		{ "__interrupt__", xLEX_INTERRUPT, -1 },
		{ "interrupt", xLEX_INTERRUPT, -1 },
		{ "inline", xLEX_INLINE, -1 },
		{ "__inline", xLEX_INLINE, -1 },
		{ "__inline__", xLEX_INLINE, -1 },
		{ "asm", xLEX_INLINEASM, -1 },
		{ "__asm", xLEX_INLINEASM, -1 },
		{ "__asm__", xLEX_INLINEASM, -1 },
		{ "far", xLEX_FAR, -1 },
		{ "near", xLEX_NEAR, -1 },
		{ "__far", xLEX_FAR, -1 },
		{ "__near", xLEX_NEAR, -1 },
		{ "packed",	xLEX_SKIPTOKEN, -1 },
		{ "unpacked", xLEX_SKIPTOKEN, -1 },
		{ "__direct", xLEX_SKIPTOKEN, -1 },
		{ "__io", xLEX_SKIPTOKEN, -1 },
		{ "__INTADDR__", xLEX_SKIPTOKEN, -1 },
		{ "__ALIGNOF__", xLEX_SKIPTOKEN, -1 },
		{ "__attribute__", xLEX_ATTRIBUTE, - 1 },
		{ NULL, xLEX_UNDEFINED, -1 } };

typedef struct _RESERVEOTHERS {
	U4 ulPpKind; /* 前処理ﾄｰｸﾝ種別			*/
	U4 ulKind; /* ﾄｰｸﾝ種別				*/
	PSZ pszToken;
} RESERVEOTHERS, *PRESERVEOTHERS;

static const RESERVEOTHERS stReservedOther[] = {
		{ xPPTOKEN_OTHER, xLEX_UNDEFINED, " " },
		{ xPPTOKEN_EQUEQU, xLEX_EQUEQU, "==" },
		{ xPPTOKEN_EQU, xLEX_EQU, "=" },
		{ xPPTOKEN_NOTEQU, xLEX_NOTEQU, "!=" },
		{ xPPTOKEN_NOT, xLEX_NOT, "!" },
		{ xPPTOKEN_POINTERMEM, xLEX_MEMREFP, "->" },
		{ xPPTOKEN_DEC, xLEX_DEC,"--" },
		{ xPPTOKEN_SUBEQU, xLEX_SUBEQU, "-=" },
		{ xPPTOKEN_SUB,	xLEX_SUB, "-" },
		{ xPPTOKEN_INC, xLEX_INC, "++" },
		{ xPPTOKEN_ADDEQU, xLEX_ADDEQU, "+=" },
		{ xPPTOKEN_ADD, xLEX_ADD, "+" },
		{ xPPTOKEN_LSHTEQU, xLEX_SHLEQU, "<<=" },
		{ xPPTOKEN_LSHT, xLEX_SHL, "<<" },
		{ xPPTOKEN_LESSEQU,	xLEX_LESSEQU, "<=" },
		{ xPPTOKEN_LESS, xLEX_LESS, "<" },
		{xPPTOKEN_RSHTEQU, xLEX_SHREQU, ">>=" },
		{ xPPTOKEN_RSHT,xLEX_SHR, ">>" },
		{ xPPTOKEN_MOREEQU, xLEX_GRTREQU, ">=" },
		{ xPPTOKEN_MORE, xLEX_GRTR, ">" },
		{ xPPTOKEN_OROR, xLEX_LOR, "||" },
		{ xPPTOKEN_OREQU, xLEX_OREQU, "|=" },
		{ xPPTOKEN_OR, xLEX_OR, "|" },
		{ xPPTOKEN_ANDAND, xLEX_LAND, "&&" },
		{ xPPTOKEN_ANDEQU, xLEX_ANDEQU, "&=" },
		{ xPPTOKEN_AND, xLEX_AND,"&" },
		{ xPPTOKEN_MULEQU, xLEX_MULEQU, "*=" },
		{ xPPTOKEN_MUL,	xLEX_MUL, "*" },
		{ xPPTOKEN_DIVEQU, xLEX_DIVEQU, "/=" },
		{ xPPTOKEN_DIV, xLEX_DIV, "/" },
		{ xPPTOKEN_MODEQU, xLEX_MODEQU,"%=" },
		{ xPPTOKEN_MOD, xLEX_MOD, "%" },
		{ xPPTOKEN_XOREQU,xLEX_XOREQU, "^=" },
		{ xPPTOKEN_XOR, xLEX_XOR, "^" },
		{xPPTOKEN_SHARPSHARP, xLEX_UNDEFINED, "##" },
		{ xPPTOKEN_SHARP,xLEX_UNDEFINED, "#" },
		{ xPPTOKEN_ELLIPSIS, xLEX_ELLIPSIS, "..." },
		{ xPPTOKEN_DOT,	xLEX_MEMREF, "." },
		{ xPPTOKEN_OPENARRAY, xLEX_OPENARRAY, "[" },
		{ xPPTOKEN_CLOSEARRAY, xLEX_CLOSEARRAY, "]" },
		{ xPPTOKEN_OPENPAREN,xLEX_OPENPAREN, "(" },
		{ xPPTOKEN_CLOSEPAREN, xLEX_CLOSEPAREN,")" },
		{ xPPTOKEN_NEG, xLEX_NEG, "~" },
		{ xPPTOKEN_QUESTION,xLEX_QUESTION, "?" },
		{ xPPTOKEN_COLON, xLEX_COLON, ":" },
		{xPPTOKEN_COMMA, xLEX_COMMA, "," },
		{ xPPTOKEN_OPENBLOCK,xLEX_OPENBLOCK, "{" },
		{ xPPTOKEN_CLOSEBLOCK, xLEX_CLOSEBLOCK,"}" },
		{ xPPTOKEN_SEMICOLON, xLEX_SEMICOLON, ";" } };

/*_____[ ｴｽｹｰﾌﾟ文字列の変換情報 ]_______________________________________*/
static const struct _ESCAPECHAR {
	UCHAR uchSrc; /* ｴｽｹｰﾌﾟ文字変換元		*/
	UCHAR uchDst; /* ｴｽｹｰﾌﾟ文字変換先		*/
} stEscapeChar[] = {
		{ 'a', '\a' }, /* BEL: alert			*/
		{ 'b', '\b' }, /* BS: back space		*/
		{ 'f', '\f' }, /* FF: form feed		*/
		{ 'n', '\n' }, /* LF: line feed		*/
		{ 'r', '\r' }, /* CR: carriage return		*/
		{ 't', '\t' }, /* HT: horizontal tab		*/
		{ 'v', '\v' }, /* VT: vertical tab		*/
		{ '\\', '\\' }, /* \				*/
		{ '\'', '\'' }, /* '				*/
		{ '"', '"' }, /* "				*/
		{ '?', '\?' }, { '\0', '\0' } /* 検索ｽﾄｯﾊﾟｰ			*/
};

typedef struct _LEXTOKEN {
	U4 ulTokenKind; /* 2 */
	AST astCodeScp; /* 3 */
	AST astType; /* 4 */
	AST astParam; /* 6 */
	PSZ pszName; /* 5 */
} TOKENBUF, *PTOKENBUF;
#define IS_PPNUM_SIGN(a)  (((a) == '+') || ((a) == '-'))
#define IS_PPNUM_START(a) ( isdigit( a ) || ((a) == '.' ))

#define ESCAPEFLAG_ILLEGAL_HEX 2
#define ESCAPEFLAG_ILLEGAL_OCT 3
#define ESCAPEFLAG_UNKNOWN 4
#define ESCAPEFLAG_OVERFLOW_HEX 5
#define ESCAPEFLAG_OVERFLOW_OCT 6

static S4 ccLexNew(TOKENBUF* tokenBuf);
static VOID ccLexGetSymbolByStr(PSZ pszStart, PTOKENBUF pstToken);
/**************************************************************************
 * break a pptoken which is wrong to three tokens
 * ex. 0x123e-0x1234
 *     0x123e+sizeof(int)
 **************************************************************************/
static AST ccLexTrytoBreakPPNum(PSZ pszStr, PTOKENBUF pstToken) {
	register PSZ pszCnt;
	CHAR cTemp;
	AST astValue = 0;
	AST astToken=0;
	S4 i;

	pszCnt = pszStr;
	while (*pszCnt != '\0') {
		if (IS_PPNUM_SIGN(*pszCnt)) {
			break;
		}
		pszCnt++;
	}
	cTemp = *pszCnt;
	*pszCnt = '\0';
	if (IS_PPNUM_START(*pszStr)) {
		astValue = CcValueAddOrign(pszStr);
		if (astValue>=MIN_ARRAY) {
			pstToken->astParam = astValue;
			pstToken->astType = stValueInfoAccess.type.get(astValue);
			pstToken->pszName = pszStr;
			pstToken->ulTokenKind = xLEX_CONSTVALUE;
			astToken = ccLexNew(pstToken);
		}
	} else {
		ccLexGetSymbolByStr(pszStr, pstToken);
		astToken = ccLexNew(pstToken);
	}
	if (cTemp != '\0') {
		pszStr = pszCnt + 1;
		*pszCnt = cTemp;
		cTemp = *pszStr;
		*pszStr = '\0';
		for (i = 0; i < sizeof(stReservedOther) / sizeof(RESERVEOTHERS); i++) {
			if (0 == strcmp(stReservedOther[i].pszToken, pszCnt)) {
				pstToken->ulTokenKind = stReservedOther[i].ulKind;
				pstToken->pszName = stReservedOther[i].pszToken;
				pstToken->astType = 0;
				pstToken->astParam = 0;
				ccLexNew(pstToken);
			}
		}
		*pszStr = cTemp;
		ccLexTrytoBreakPPNum(pszStr, pstToken);
	}
	return astToken;
}
/**************************************************************************
 * get a operator token.
 **************************************************************************/
static AST ccLexGetOther(AST astCurrPPToken,PTOKENBUF pstToken) {
	PSZ pszValue;
	U2 nPreTokenType;

	nPreTokenType = stCorePPTokenListAccess.ppTokenKind.get(astCurrPPToken);
	pstToken->astCodeScp = stCorePPTokenListAccess.codeScope.get(
			astCurrPPToken);
	pszValue = stCorePPTokenListAccess.name.get(astCurrPPToken);

	if (nPreTokenType == xPPTOKEN_SHARPSHARP || nPreTokenType == xPPTOKEN_SHARP) {
		CcThrowWarning( CC_TOKEN_UNEXPECTED,
				pstToken->astCodeScp,
				pszValue, NULL );
		pstToken->ulTokenKind = xLEX_SKIPTOKEN;
		return 0;
	}

	if ((nPreTokenType - xPPTOKEN_OTHER) >= 0
			&& (nPreTokenType - xPPTOKEN_OTHER)
					< sizeof(stReservedOther) / sizeof(stReservedOther[0])) {
		if (stReservedOther[nPreTokenType - xPPTOKEN_OTHER].ulPpKind
				== nPreTokenType) {
			pstToken->ulTokenKind = stReservedOther[nPreTokenType
					- xPPTOKEN_OTHER].ulKind;
			pstToken->pszName =
					stReservedOther[nPreTokenType - xPPTOKEN_OTHER].pszToken;

			return ccLexNew(pstToken);
		}
	}
	CcThrowWarning( CC_TOKEN_UNEXPECTED,
			pstToken->astCodeScp,
			pszValue, NULL );
	pstToken->ulTokenKind = xLEX_UNDEFINED;
	pstToken->pszName = pszValue;

	return (0);
}
/***********************************************************
 * analyze a symbol
 ***********************************************************/
static VOID ccLexGetSymbolByStr(PSZ pszStart, PTOKENBUF pstToken) {
	S4 i;
	pstToken->pszName = pszStart;
	if (str_length( pszStart ) == 0) {
		pstToken->ulTokenKind = xLEX_SKIPTOKEN;
		return;
	}
	i = tiIdxReservedWord[(S4) (*pszStart)];

	while (i != -1) {
		if (!strcmp(stReservedWord[i].pszToken, pszStart)) {
			pstToken->ulTokenKind = stReservedWord[i].ulKind;
			pstToken->pszName = stReservedWord[i].pszToken;
			/** keyword **/
			return;
		}
		i = stReservedWord[i].iNext;
	}

	pstToken->ulTokenKind = xLEX_SYMBOL;
	pstToken->astType = (AST) 0;
}
/***********************************************************
 * create a symbol token.
 ***********************************************************/
static AST ccLexGetSymbol(AST astCurrPPToken, PTOKENBUF pstToken) {
	PSZ pszStart;

	pstToken->astCodeScp = stCorePPTokenListAccess.codeScope.get(
			astCurrPPToken);
	pszStart = stCorePPTokenListAccess.name.get(astCurrPPToken);
	ccLexGetSymbolByStr(pszStart, pstToken);

	return ccLexNew(pstToken);
}
/***********************************************************
 * Get the maximum value of escape sequences
 ***********************************************************/
static U4 ccLexGetCharMaxValue(U4 charKind) {
	/*  wchar_t 未対応    */
	return U1_MAXVALUE;
}
/***********************************************************
 * Check whether a escape sequence is overflow.
 ***********************************************************/
static BOOL ccLexIsOverflowChar(U4 ulVal, U4 charKind) {
	if (ulVal > ccLexGetCharMaxValue(charKind)) {
		return TRUE;
	}
	return FALSE;
}
/***********************************************************
 * analyze escape sequences which are in character-constant
 *   or in string literals.
 ***********************************************************/
static S4 ccLexGetEscapeChar(PSZ pszIn, PSZ *ppszOut, U4 charKind,
		S4 *pErrorFlg) {
	U4 ulVal = 0;
	S4 i;
	S4 errorflg = FALSE;

	if (*pszIn == 'x') {
		ulVal = 0L;
		pszIn++;

		for (i = 0; isxdigit(*pszIn); i++, pszIn++) {
			if (ccLexIsOverflowChar(ulVal, charKind)) {
				errorflg = ESCAPEFLAG_OVERFLOW_HEX;
				ulVal = ccLexGetCharMaxValue(charKind);
			} else {
				if (isdigit(*pszIn)) {
					ulVal = (ulVal << 4) | (*pszIn - '0');
				} else {
					ulVal = (ulVal << 4) | (toupper(*pszIn) - 'A' + 0x0A);
				}
			}
		}

		if (i == 0) {
			errorflg = ESCAPEFLAG_ILLEGAL_HEX;
			ulVal = 'x';
		}
	} else if (*pszIn >= '0' && *pszIn <= '7') {
		ulVal = 0L;

		for (i = 0; (i < 3) && (*pszIn >= '0') && (*pszIn <= '7');
				i++, pszIn++) {
			if (ccLexIsOverflowChar(ulVal, charKind)) {
				errorflg = ESCAPEFLAG_OVERFLOW_OCT;
				ulVal = ccLexGetCharMaxValue(charKind);
			} else {
				ulVal = (ulVal << 3) + (*pszIn - '0');
			}
		}

	} else {
		for (i = 0; stEscapeChar[i].uchSrc != '\0'; i++) {
			if (stEscapeChar[i].uchSrc == *pszIn) {
				break;
			}
		}

		if (stEscapeChar[i].uchSrc != '\0') {
			ulVal = stEscapeChar[i].uchDst;
		} else {
			ulVal = *pszIn;
			errorflg = ESCAPEFLAG_UNKNOWN;
		}
		pszIn++;
	}
	*ppszOut = pszIn;
	*pErrorFlg = errorflg;
	return ulVal;
}
/***********************************************************
 * create a string literal token
 ***********************************************************/
static AST ccLexGetStringEnd(PTOKENBUF pstToken) {
	return ccLexNew(pstToken);
}
/***********************************************************
 * analyze string literals
 ***********************************************************/
static U4 ccLexGetString(AST astCurrPPToken,PTOKENBUF pstToken, U4 ulPreKind ) {
	CHAR* pToken; /*前処理字句ポインタ*/
	CHAR* pStartAddress; /*開始アドレス*/
	U4 RetUlong;
	S4 StrLen; /*文字数*/
	S4 errorFlg;
	AST bufferIdx;
	AST astCodeScp;
	PSZ buffer;
	AST astType;
	S4 lVal;
	U4 ulCurrKind=0;
	pToken = stCorePPTokenListAccess.name.get( astCurrPPToken );
	if (*pToken == 'L') {
		pToken++;

		if (ulPreKind == STRING_CHARSTRING) {
			CcThrowWarning( CC_TOKEN_STRING_KIND_DIFF,
					stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
					stCorePPTokenListAccess.name.get( astCurrPPToken ), NULL );
		} else {
			ulCurrKind = STRING_WIDESTRING;
		}
	} else {
		if (ulPreKind == STRING_WIDESTRING) {
			CcThrowWarning( CC_TOKEN_STRING_KIND_DIFF,
					stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
					stCorePPTokenListAccess.name.get( astCurrPPToken ), NULL );
		} else {
			ulCurrKind = STRING_CHARSTRING;
		}
	}
	/*「前処理字句ポインタ」を前に1文字で進める	*/
	pToken++;

	pStartAddress = pToken;
	bufferIdx = stCcLabelStrAccess.addStr(pStartAddress);
	if (bufferIdx != 0) {
		buffer = stCcLabelStrAccess.getStr(bufferIdx);
	} else {
		return ulCurrKind;
	}
	StrLen = 0;
	while (*pToken != '\0') {
		if (*pToken == '\"') {
			break;
		}

		if (*pToken == '\\') {
			pToken++;
			errorFlg = 0;
			lVal = ccLexGetEscapeChar(pToken, &pToken, ulCurrKind, &errorFlg);
			switch (errorFlg) {
			case ESCAPEFLAG_ILLEGAL_HEX:
				CcThrowWarning( CC_TOKEN_STRING_HEX_ILLEGAL,
						stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
						pToken, NULL );
				break;
			case ESCAPEFLAG_ILLEGAL_OCT:
				CcThrowWarning( CC_TOKEN_STRING_OCT_ILLEGAL,
						stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
						pToken, NULL );
				break;
			case ESCAPEFLAG_OVERFLOW_HEX:
				CcThrowWarning( CC_TOKEN_STRING_HEX_OVERFLOW,
						stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
						pToken, NULL );
				break;
			case ESCAPEFLAG_OVERFLOW_OCT:
				CcThrowWarning( CC_TOKEN_STRING_OCT_OVERFLOW,
						stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
						pToken, NULL );
				break;
			case ESCAPEFLAG_UNKNOWN:
				CcThrowWarning( CC_TOKEN_CHAR_UNKNOWN_ESCAPE,
					stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
					pToken, NULL );
				break;
			}
			StrLen++;
			*buffer = lVal;
			buffer++;
		} else {
			StrLen++;
			*buffer = *pToken;
			pToken++;
			buffer++;
		}
	}

	*pToken = '\0';
	*buffer = '\0';
	if (ulPreKind == STRING_NONE) {
		pstToken->astCodeScp = stCorePPTokenListAccess.codeScope.get(
				astCurrPPToken);
		pstToken->pszName = pStartAddress;

		pstToken->ulTokenKind = xLEX_CONSTSTR;
		if (ulCurrKind == STRING_WIDESTRING) {
			astType = CcTypeGetWCharType();
		} else {
			astType = TYPE_CHAR;
		}
		pstToken->astType = CcTypeAddArray(astType, StrLen + 1 );
		pstToken->astParam = stCcConstStringAccess.addStr(buffer, StrLen + 1);
	} else {
		RetUlong = stTypeInfoAccess.size.get(pstToken->astType);
		RetUlong += StrLen;
		pstToken->astType = CcTypeResetArraySize( pstToken->astType, RetUlong );
		astCodeScp = stCorePPTokenListAccess.codeScope.get(astCurrPPToken);
		pstToken->astCodeScp = stCoreCodeScpAccess.mergeCodeScp(
				pstToken->astCodeScp, astCodeScp);
		pstToken->astParam = stCcConstStringAccess.appendStr(pstToken->astParam,
				buffer, StrLen);
		bufferIdx = stCcLabelStrAccess.addStr(pstToken->pszName);
		bufferIdx = stCcLabelStrAccess.appendStr(bufferIdx, pStartAddress);
		pstToken->pszName = stCcLabelStrAccess.getStr(bufferIdx);
	}
	return (ulCurrKind);
}

/***********************************************************
 * analyze a integer-constant or floating-constant
 ***********************************************************/
static AST ccLexGetNumber(AST astCurrPPToken,PTOKENBUF pstToken) {
	PSZ pszStart;
	AST astValue; /* 値情報ﾃﾝﾎﾟﾗﾘ		*/

	pstToken->astCodeScp = stCorePPTokenListAccess.codeScope.get(
			astCurrPPToken);
	pszStart = stCorePPTokenListAccess.name.get(astCurrPPToken);
	if (str_length( pszStart ) == 0) {
		pstToken->ulTokenKind = xLEX_SKIPTOKEN;
		return 0;
	}

	astValue = CcValueAddOrign(pszStart);
	if (astValue == 0) {
		return ccLexTrytoBreakPPNum(pszStart, pstToken);
	}
	pstToken->pszName = pszStart;
	pstToken->astParam = astValue;
	pstToken->ulTokenKind = xLEX_CONSTVALUE;
	pstToken->astType = stValueInfoAccess.type.get(astValue);
	return ccLexNew(pstToken);
}

/***********************************************************
 * analyze a character-constant
 ***********************************************************/
static AST ccLexGetChar(AST astCurrPPToken, PTOKENBUF pstToken) {
	U4 lVal;
	PSZ pszValue;
	VARVALUE buf;
	S4 errorFlg = 0;
	U4 ulCurrKind = STRING_CHARSTRING;

	pszValue = stCorePPTokenListAccess.name.get(astCurrPPToken);
	pstToken->astCodeScp = stCorePPTokenListAccess.codeScope.get(
			astCurrPPToken);
	pstToken->ulTokenKind = xLEX_CONSTVALUE;
	pstToken->astType = TYPE_INT;

	if (*pszValue == 'L') {
		pszValue++;
		ulCurrKind = STRING_WIDESTRING;
	}
	pstToken->pszName = pszValue;
	pszValue++;

	if (*pszValue == '\'') {
		CcThrowWarning( CC_TOKEN_CHAR_BLANK,
			stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
			pstToken->pszName, NULL );
		lVal = 0;
	} else if (*pszValue == '\\') {
		pszValue++;
		errorFlg = 0;
		lVal = ccLexGetEscapeChar(pszValue, &pszValue, ulCurrKind, &errorFlg);
		switch (errorFlg) {
		case ESCAPEFLAG_ILLEGAL_HEX:
			CcThrowWarning( CC_TOKEN_CHAR_HEX_ILLEGAL,
				stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
				pstToken->pszName, NULL );
			break;
		case ESCAPEFLAG_ILLEGAL_OCT:
			CcThrowWarning( CC_TOKEN_CHAR_OCT_ILLEGAL,
				stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
				pstToken->pszName, NULL );
			break;
		case ESCAPEFLAG_OVERFLOW_HEX:
			CcThrowWarning( CC_TOKEN_CHAR_HEX_OVERFLOW,
				stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
				pstToken->pszName, NULL );
			break;
		case ESCAPEFLAG_OVERFLOW_OCT:
			CcThrowWarning( CC_TOKEN_CHAR_OCT_OVERFLOW,
				stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
				pstToken->pszName, NULL );
			break;
		case ESCAPEFLAG_UNKNOWN:
			CcThrowWarning( CC_TOKEN_CHAR_UNKNOWN_ESCAPE,
				stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
				pstToken->pszName, NULL );
			break;
		}
	} else {
		if (IS_MULTI_CHAR( *pszValue )) {
			CcThrowWarning( CC_TOKEN_CHAR_MULTIBYTE,
				stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
				pstToken->pszName, NULL );
			lVal = *pszValue;
			pszValue += 2;
		} else {
			lVal = *pszValue;
			pszValue++;
		}
	}

	if (*pszValue != '\'' && *pszValue != '\0') {
		CcThrowWarning( CC_TOKEN_CHAR_MULTICHAR,
			stCorePPTokenListAccess.codeScope.get( astCurrPPToken ),
			pstToken->pszName, NULL );
	}
	buf.sign = 1;
	buf.u8Remainder = lVal;
	pstToken->astParam = CcValueAddVarValue( TYPE_INT, buf);

	return ccLexNew(pstToken);
}
/***********************************************************
 * create a new token.
 ***********************************************************/
static AST ccLexNew(TOKENBUF* tokenBuf) {
	AST astNew;

	stLexTokenAccess.alloc(1);
	astNew = stLexTokenAccess.getMax();
	if (tokenBuf->ulTokenKind)
		stLexTokenAccess.tokenKind.set(astNew, tokenBuf->ulTokenKind);
	if (tokenBuf->astType)
		stLexTokenAccess.type.set(astNew, tokenBuf->astType);
	if (tokenBuf->astParam)
		stLexTokenAccess.paramIdx.set(astNew, tokenBuf->astParam);
	if (tokenBuf->astCodeScp)
		stLexTokenAccess.codeScp.set(astNew, tokenBuf->astCodeScp);
	if (tokenBuf->pszName != NULL)
		stLexTokenAccess.name.set(astNew, tokenBuf->pszName);
	return astNew;
}
/***********************************************************
 * initial
 ***********************************************************/
VOID CcLexInit(AST astTranslation) {
	S4 i;
	S4 *piIndex;

	static BOOL bOpened = FALSE;

	gblCurrToken = 0;
	CppResultGetFirstPPToken(astTranslation);
	if (stLexTokenAccess.getMax() > 0) {
		stLexTokenAccess.clear();
	}

	if (bOpened == FALSE) {
		for (i = 0;
				i < sizeof(tiIdxReservedWord) / sizeof(tiIdxReservedWord[0]);
				i++) {
			tiIdxReservedWord[i] = -1;
		}

		for (i = 0; stReservedWord[i].pszToken != NULL; i++) {
			piIndex = &tiIdxReservedWord[(S4) (stReservedWord[i].pszToken[0])];

			while (*piIndex != -1) {
				piIndex = &stReservedWord[*piIndex].iNext;
			}

			*piIndex = i;
		}

		bOpened = TRUE;
	}

}
/******************************************************************
 * return the current token.
 *******************************************************************/
AST CcLexGetCurrToken(VOID) {
	return gblCurrToken;
}
/******************************************************************
 * return the next token of current token.
 * return a xLEX_ENDOFFILE token when finished.
 *******************************************************************/
AST CcLexGetNextToken(VOID) {
	AST nKindMax;
	AST astCurrPPToken;
	U4 lPreKind;
	TOKENBUF stTokenBuf = { 0 };


	nKindMax = stLexTokenAccess.getMax();
	if (gblCurrToken < nKindMax) {
		gblCurrToken++;
		return (gblCurrToken);
	}
	astCurrPPToken = CppResultGetCurrPPToken();
	if (astCurrPPToken == 0) {
		if (stLexTokenAccess.tokenKind.get(
				stLexTokenAccess.getMax()) == xLEX_ENDOFFILE) {
			;
		}else{
			gblCurrToken++;
			stTokenBuf.ulTokenKind = xLEX_ENDOFFILE;
			gblCurrToken = ccLexNew(&stTokenBuf);
		}
		return gblCurrToken;
	}

	lPreKind = STRING_NONE;
	while (astCurrPPToken) {
		ulPreTokenKind = stCorePPTokenListAccess.ppTokenKind.get(
				astCurrPPToken);
		switch (ulPreTokenKind) {
		case xPPTOKEN_PPNUM:
			gblCurrToken = ccLexGetNumber(astCurrPPToken, &stTokenBuf);
			astCurrPPToken = CppResultGetNextPPToken();
			lPreKind = STRING_NONE;
			break;

		case xPPTOKEN_CHAR:
			gblCurrToken = ccLexGetChar(astCurrPPToken,&stTokenBuf);
			astCurrPPToken = CppResultGetNextPPToken();
			lPreKind = STRING_NONE;
			break;

		case xPPTOKEN_STR:
			lPreKind = ccLexGetString(astCurrPPToken,&stTokenBuf, lPreKind );
			astCurrPPToken = CppResultGetNextPPToken();
			ulPreTokenKind = stCorePPTokenListAccess.ppTokenKind.get(
					astCurrPPToken);
			if (ulPreTokenKind == xPPTOKEN_STR) {
				continue;
			} else {
				gblCurrToken = ccLexGetStringEnd(&stTokenBuf);
			}
			break;

		case xPPTOKEN_SYM:
			gblCurrToken = ccLexGetSymbol(astCurrPPToken,&stTokenBuf);
			astCurrPPToken = CppResultGetNextPPToken();
			lPreKind = STRING_NONE;
			break;
		case xPPTOKEN_PRAGMABEGIN:
			lPreKind = STRING_NONE;
			if (CcPragma != NULL) {
				CcPragma();
			} else {
				while (astCurrPPToken) {
					ulPreTokenKind = stCorePPTokenListAccess.ppTokenKind.get(
							astCurrPPToken);
					if (ulPreTokenKind == xPPTOKEN_PRAGMAEND) {
						break;
					}
					astCurrPPToken = CppResultGetNextPPToken();
				}
				astCurrPPToken = CppResultGetNextPPToken();
			}
			break;
		default:
			gblCurrToken = ccLexGetOther(astCurrPPToken,&stTokenBuf);
			astCurrPPToken = CppResultGetNextPPToken();
			lPreKind = STRING_NONE;
			break;
		}

		if (stTokenBuf.ulTokenKind == xLEX_SKIPTOKEN ) {
			continue;
		}
		if (gblCurrToken != 0) {
			break;
		}
	}
	return gblCurrToken;
}
/**************************************
 * Get the token backwards.
 **************************************/
AST CcLexGetLF(S4 num) {
	AST astToken = gblCurrToken - num;
	if (astToken >= MIN_ARRAY) {
		return astToken;
	}
	return 0;
}
/**************************************
 * Get the token ahead.
 **************************************/
AST CcLexGetRT(S4 num) {
	AST astToken = gblCurrToken + num;
	AST astTemp = gblCurrToken;

	while (astToken > stLexTokenAccess.getMax()) {
		gblCurrToken = stLexTokenAccess.getMax();
		CcLexGetNextToken();
		if (stLexTokenAccess.tokenKind.get(
				stLexTokenAccess.getMax()) == xLEX_ENDOFFILE) {
			astToken = 0;
			break;
		}
	}
	gblCurrToken = astTemp;
	return astToken;
}
/**************************************
 * Jump back.
 **************************************/
VOID CcLexBackto(AST token) {
	if (token <= gblCurrToken && token >= MIN_ARRAY) {
		gblCurrToken = token;
	}
}
/**************************************
 * get the final one
 **************************************/
AST CcLexGetLastOne(VOID ){
	return stLexTokenAccess.getMax();
}
